#include "QNinePatch.h"


#define CHUNK_MASK 0xff000000

QNinePatch::QNinePatch(QString imgPath)
{
    mOrgData = new QPixmap(imgPath, QFileInfo(imgPath).suffix().toAscii().data());
    int w = mOrgData->width();
    int h = mOrgData->height();

    QImage orgImg(w, h, QImage::Format_ARGB32_Premultiplied);
    orgImg.load(imgPath, QFileInfo(imgPath).suffix().toAscii().data());

    QList<QPoint*> hChunkPoint;
    QList<QPoint*> vChunkPoint;
    QList<QPoint*> hNoneChunkPoint;
    QList<QPoint*> vNoneChunkPoint;

    int noneCheckLength = 0;
    int checkLength = 0;

    for(int i = 0; i < w; i++){
        QRgb rgb = orgImg.pixel(i, 0);
        if( rgb == CHUNK_MASK ){
            if(noneCheckLength != 0){
                QPoint* nonePoint = new QPoint(i-noneCheckLength, noneCheckLength);
                hNoneChunkPoint.append(nonePoint);
                noneCheckLength = 0;
            }
            checkLength++;
        } else {
            if(checkLength != 0){
                QPoint* point = new QPoint(i-checkLength, checkLength);
                hChunkPoint.append(point);
                checkLength = 0;
            }
            noneCheckLength++;
        }
    }

    if(noneCheckLength != 0){
        QPoint* nonePoint = new QPoint(w-noneCheckLength, noneCheckLength);
        hNoneChunkPoint.append(nonePoint);
        noneCheckLength = 0;
    }

    if(checkLength != 0){
        QPoint* point = new QPoint(w-checkLength, checkLength);
        hChunkPoint.append(point);
        checkLength = 0;
    }

    for(int i = 0; i < h; i++){
        QRgb rgb = orgImg.pixel(0, i);
        if( rgb == CHUNK_MASK ){
            if(noneCheckLength != 0){
                QPoint* nonePoint = new QPoint(i-noneCheckLength, noneCheckLength);
                vNoneChunkPoint.append(nonePoint);
                noneCheckLength = 0;
            }
            checkLength++;
        } else {
            if(checkLength != 0){
                QPoint* point = new QPoint(i-checkLength, checkLength);
                vChunkPoint.append(point);
                checkLength = 0;
            }
            noneCheckLength++;
        }
    }

    if(noneCheckLength != 0){
        QPoint* nonePoint = new QPoint(h-noneCheckLength, noneCheckLength);
        vNoneChunkPoint.append(nonePoint);
        noneCheckLength = 0;
    }

    if(checkLength != 0){
        QPoint* point = new QPoint(h-checkLength, checkLength);
        vChunkPoint.append(point);
        checkLength = 0;
    }

    int column = hChunkPoint.size();
    int row = vChunkPoint.size();

    if(column > 0 && row > 0){
        for(int i = 0; i < column; i++){
            int x = hChunkPoint.at(i)->x();
            int w = hChunkPoint.at(i)->y();
            for(int j = 0; j < row; j++){
                int y = vChunkPoint.at(j)->x();
                int h = vChunkPoint.at(j)->y();
                QRect rect;
                rect.setRect(x,y,w,h);
                mChunkRect.append(rect);
            }
        }

        column = hNoneChunkPoint.size();
        row = vNoneChunkPoint.size();

        for(int i = 0; i < column; i++){
            int x = hNoneChunkPoint.at(i)->x();
            int w = hNoneChunkPoint.at(i)->y();
            for(int j = 0; j < row; j++){
                int y = vNoneChunkPoint.at(j)->x();
                int h = vNoneChunkPoint.at(j)->y();
                QRect rect;
                rect.setRect(x,y,w,h);
                mNoneChunkRect.append(rect);
            }
        }
        isNinePatch = true;
    } else
        isNinePatch = false;

    hChunkPoint.clear();
    vChunkPoint.clear();
    hNoneChunkPoint.clear();
    vNoneChunkPoint.clear();
}

QNinePatch::~QNinePatch(){
    mNoneChunkRect.clear();
    mChunkRect.clear();
    mPatchList.clear();
    delete mOrgData;
}

#define MATCH_TOP       0x0001
#define MATCH_LEFT      0x0002
#define MATCH_RIGHT     0x0004
#define MATCH_BOTTOM    0x0008

QList<QNinePatchItem*> QNinePatch::getResizePatch(){
    QList<QNinePatchItem*> resizePatchs;
    int reCount = mPatchList.size();
    for(int i = 0; i < reCount; i++){

    }
}

QImage QNinePatch::getNinePatchPicture(QSize size){
    QImage img(size, QImage::Format_ARGB32_Premultiplied);
    QPainter painter(&img);

    if(mOrgData->size().width() <= size.width() && mOrgData->size().height() <= size.height() && isNinePatch){
        noneChunkPaint(&painter, size);
        chunkPaint(&painter, size);
    } else
        painter.drawPixmap(0, 0, size.width(), size.height(), mOrgData->copy(QRect(QPoint(0,0),size)));

    painter.setCompositionMode(QPainter::CompositionMode_SourceOut);
    QPen pen(QColor(0,0,0,255));
    pen.setWidth(2);
    pen.setCapStyle(Qt::FlatCap);
    pen.setJoinStyle(Qt::MiterJoin);
    pen.setStyle(Qt::SolidLine);

    painter.setRenderHint(QPainter::Antialiasing, true);
    painter.setPen(pen);
    painter.setBrush(QBrush(QColor(0,0,0,255), Qt::SolidPattern));

    int checkLength = 0;
    int w = size.width();
    int h = size.height();
    for(int i = 0; i < w; i++){
        QRgb rgb = img.pixel(i, 0);
        if( rgb == CHUNK_MASK ){
            checkLength++;
        } else if(checkLength != 0) {
            QLine line(i-checkLength, 0, i, 0);
            painter.drawLine(line);
            checkLength = 0;
        }
    }

    for(int i = 0; i < h; i++){
        QRgb rgb = img.pixel(0, i);
        if( rgb == CHUNK_MASK ){
            checkLength++;
        } else if(checkLength != 0) {
            QLine line(0 ,i-checkLength, 0, i);
            painter.drawLine(line);
            checkLength = 0;
        }
    }

    int refY = h - 1;
    for(int i = 0; i < w; i++){
        QRgb rgb = img.pixel(i, refY);
        if( rgb == CHUNK_MASK ){
            checkLength++;
        } else if(checkLength != 0) {
            QLine line(i-checkLength, h, i, h);
            painter.drawLine(line);
            checkLength = 0;
        }
    }

    int refX = w - 1;
    for(int i = 0; i < h; i++){
        QRgb rgb = img.pixel(refX, i);
        if( rgb == CHUNK_MASK ){
            checkLength++;
        } else if(checkLength != 0) {
            QLine line(w ,i-checkLength, w, i);
            painter.drawLine(line);
            checkLength = 0;
        }
    }

    return img;
}

void QNinePatch::noneChunkPaint(QPainter* painter, QSize size){
    QRect orgRect = mOrgData->rect();
    int count = mNoneChunkRect.size();
    for(int i = 0; i < count; i++){
        QRect rect = mNoneChunkRect.at(i);
        int status = 0;
        int xpos = 0;
        int ypos = 0;
        int width = 0;
        int height = 0;

        if(rect.left() == orgRect.left()) status |= MATCH_LEFT;
        if(rect.right() == orgRect.right()) status |= MATCH_RIGHT;
        if(rect.top() == orgRect.top()) status |= MATCH_TOP;
        if(rect.bottom() == orgRect.bottom()) status |= MATCH_BOTTOM;

        switch(status){
        case MATCH_LEFT:
            break;
        case MATCH_RIGHT:
            break;
        case MATCH_TOP:
            break;
        case MATCH_BOTTOM:
            break;
        case MATCH_LEFT|MATCH_TOP:
            xpos = rect.x();
            ypos = rect.y();
            width = rect.width();
            height = rect.height();
            painter->drawPixmap(xpos, ypos, width, height, mOrgData->copy(xpos, ypos, width, height));
            break;
        case MATCH_LEFT|MATCH_BOTTOM:
            xpos = rect.x();
            ypos = size.height() - rect.height();
            width = rect.width();
            height = rect.height();
            painter->drawPixmap(xpos, ypos, width, height, mOrgData->copy(rect.x(), rect.y(), width, height));
            break;
        case MATCH_RIGHT|MATCH_TOP:
            xpos = size.width() - rect.width();
            ypos = rect.y();
            width = rect.width();
            height = rect.height();
            painter->drawPixmap(xpos, ypos, width, height, mOrgData->copy(rect.x(), rect.y(), width, height));
            break;
        case MATCH_RIGHT|MATCH_BOTTOM:
            xpos = size.width() - rect.width();
            ypos = size.height() - rect.height();
            width = rect.width();
            height = rect.height();
            painter->drawPixmap(xpos, ypos, width, height, mOrgData->copy(rect.x(), rect.y(), width, height));
            break;
        default:
            break;
        }
    }
}

void QNinePatch::chunkPaint(QPainter* painter, QSize size){
    int count = 0;
    int orgWidth = mOrgData->width();
    int orgHeight = mOrgData->height();

    count = mChunkRect.size();
    for(int i = 0; i < count; i++){
        QRect rect = mChunkRect.at(i);
        int xpos = rect.x();
        int ypos = rect.y();
        int width = (size.width() - (orgWidth - rect.width())) / count;
        int height = (size.height() - (orgHeight - rect.height())) / count;
        painter->drawPixmap(xpos, ypos, width, height, mOrgData->copy(rect));

        int nonecount = mNoneChunkRect.size();

        for(int j = 0; j < nonecount; j++){
            if(mNoneChunkRect.at(j).right()+1 == rect.left() && mNoneChunkRect.at(j).bottom()+1 == rect.top()){
                painter->drawPixmap(
                            xpos,
                            ypos-mNoneChunkRect.at(j).height(),
                            width,
                            mNoneChunkRect.at(j).height(),
                            mOrgData->copy(
                                rect.x(),
                                mNoneChunkRect.at(j).y(),
                                rect.width(),
                                mNoneChunkRect.at(j).height()));

                painter->drawPixmap(
                            xpos-mNoneChunkRect.at(j).width(),
                            ypos,
                            mNoneChunkRect.at(j).width(),
                            height,
                            mOrgData->copy(
                                mNoneChunkRect.at(j).x(),
                                rect.y(),
                                mNoneChunkRect.at(j).width(),
                                rect.height()));

            } else if(mNoneChunkRect.at(j).left()-1 == rect.right() && mNoneChunkRect.at(j).top()-1 == rect.bottom()) {
                painter->drawPixmap(
                            xpos,
                            ypos+height,
                            width,
                            mNoneChunkRect.at(j).height(),
                            mOrgData->copy(
                                rect.x(),
                                mNoneChunkRect.at(j).y(),
                                rect.width(),
                                mNoneChunkRect.at(j).height()));

                painter->drawPixmap(
                            xpos+width,
                            ypos,
                            mNoneChunkRect.at(j).width(),
                            height,
                            mOrgData->copy(
                                mNoneChunkRect.at(j).x(),
                                rect.y(),
                                mNoneChunkRect.at(j).width(),
                                rect.height()));
            }
        }
    }
}
